package com.kuaimacode.kframework.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by vic.dai on 2016/10/28.
 */
public abstract class AbstractHttpExecutor {

	private String path;
	private Map<String, String> params;
	private int readTimeout;

	private String result;
	private boolean executed = false;

	private final Logger logger = LoggerFactory.getLogger(AbstractHttpExecutor.class);


	protected AbstractHttpExecutor(String path) {
		this.path = path;
		this.readTimeout = 0;
		params = new HashMap<>();
	}

	public abstract String getDomain();

	public abstract String getSignKey();

	public abstract String getPartnerId();

	public void setReadTimeout(int readTimeout) {
		this.readTimeout = readTimeout;
	}

	public AbstractHttpExecutor addParam(String key, String value) {
		if (value != null) {
			params.put(key, value);
		}
		return this;
	}

	public AbstractHttpExecutor addParamExuEmpty(String key, String value) {
        if (!StringUtils.isEmpty(value)) {
            params.put(key, value);
        }
        return this;
    }
    
	public AbstractHttpExecutor addParam(Map<String, String> params) {
		this.params.putAll(params);
		return this;
	}

	public AbstractHttpExecutor addParam(Object objectParams) {
		JSONObject jsonObject = (JSONObject) JSON.toJSON(objectParams);
		for (String key : jsonObject.keySet()) {
			if (jsonObject.get(key) instanceof JSONArray) {
				JSONArray jsonArray = (JSONArray) jsonObject.get(key);
				addListParam(key, jsonArray);
			} else {
				this.addParam(key, jsonObject.getString(key));
			}
		}
		return this;
	}

	public String getResultForString() {
		checkExecuted();
		return this.result;
	}

	public JSONObject getResultForJson() {
		checkExecuted();
		return JSON.parseObject(result);
	}

	private void checkExecuted() {
		if (!executed) {
			throw new ServerInternalErrorException("请求未触发, 不能获取结果!");
		}
	}

	public AbstractHttpExecutor doExecute(Map<String, String> params) {
		addParam(params);
		doExecute();
		return this;
	}

	public String doExecuteAndGetResult() {
		doExecute();
		return result;
	}

	public String doExecuteAndGetResult(Map<String, String> params) {
		addParam(params);
		doExecute();
		return result;
	}
	private void addListParam(String paramName, JSONArray jsonArray) {
	    boolean isPrototype = false;
		for (int i = 0; i < jsonArray.size(); i++) {
			Object object = jsonArray.getObject(i, Object.class);
			if (object instanceof JSONObject) {
                for (String key : ((JSONObject) object).keySet()) {
                    this.addParam(paramName + "[" + i + "]" + "." + key, ((JSONObject) object).getString(key));
                }
            } else {
			    isPrototype = true;
                break;
            }
		}

		if (isPrototype) {
            this.addParam(paramName, jsonArray.toJSONString());
        }
    }

	public void setCommonParams(Map<String, String> params) {

	}

	public AbstractHttpExecutor doExecute() {
		try {
			this.executed = true;
			setCommonParams(params);
			logger.info("====>>调用域:[{}]接口:[{}]请求参数为:[{}]", getDomain(), path, params);
			String httpResult = HttpUtil.postString(getDomain() + path, params, readTimeout);
			logger.info("<<====调用域:[{}]接口:[{}]响应结果为:[{}]", getDomain(), path, httpResult);
			this.result = httpResult;
			return this;
		} catch (Exception e) {
			logger.error("调用{}接口:[{}]异常!", getDomain(), path, e);
			throw new ServerInternalErrorException("调用" + getDomain() + "接口:[" + path + "]异常", e);
		}
	}
}
